package com.hiss.basic.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hiss.basic.client.system.ISysRoleMenuService;
import com.hiss.basic.client.system.ISysRoleService;
import com.hiss.basic.client.system.ISysUserRoleService;
import com.hiss.basic.client.system.ISysUserService;
import com.hiss.basic.model.system.domain.SysRoleDomain;
import com.hiss.basic.model.system.domain.SysRoleMenuDomain;
import com.hiss.basic.model.system.domain.SysUserRoleDomain;
import com.hiss.basic.model.system.request.*;
import com.hiss.basic.model.system.response.SysRoleQueryResponse;
import com.hiss.basic.model.system.response.SysUserQueryResponse;
import com.hiss.basic.starter.core.exception.BusinessException;
import com.hiss.basic.starter.core.helper.MapstructHelper;
import com.hiss.basic.starter.core.helper.ValidationHelper;
import com.hiss.basic.starter.mybatis.utils.PageUtils;
import com.hiss.basic.system.mapper.SysRoleMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 系统角色 service impl
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRoleDomain> implements ISysRoleService {

    @Resource
    private ISysRoleMenuService sysRoleMenuService;

    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Resource
    private ISysUserService sysUserService;

    @Override
    public List<SysRoleQueryResponse> findList(SysRoleQueryRequest request) {
        QueryWrapper wrapper = new QueryWrapper();
        if (ObjectUtil.isNotNull(request)) {
            wrapper.like(SysRoleDomain::getName, request.getName(), StrUtil.isNotBlank(request.getName()));
            wrapper.eq(SysRoleDomain::getCode, request.getCode(), StrUtil.isNotBlank(request.getCode()));
            wrapper.eq(SysRoleDomain::getEnableStatus, request.getEnableStatus(), ObjectUtil.isNotNull(request.getEnableStatus()));
        }
        wrapper.orderBy(SysRoleDomain::getSort, true);
        wrapper.orderBy(SysRoleDomain::getCreateTime, false);
        return listAs(wrapper, SysRoleQueryResponse.class);
    }

    @Override
    public Page<SysRoleQueryResponse> findPageList(SysRoleQueryRequest request) {
        QueryWrapper wrapper = new QueryWrapper();
        if (ObjectUtil.isNotNull(request)) {
            wrapper.like(SysRoleDomain::getName, request.getName(), StrUtil.isNotBlank(request.getName()));
            wrapper.eq(SysRoleDomain::getCode, request.getCode(), StrUtil.isNotBlank(request.getCode()));
            wrapper.eq(SysRoleDomain::getEnableStatus, request.getEnableStatus(), ObjectUtil.isNotNull(request.getEnableStatus()));
        }
        wrapper.orderBy(SysRoleDomain::getSort, true);
        wrapper.orderBy(SysRoleDomain::getCreateTime, false);

        Page page = PageUtils.getPage();
        return pageAs(page, wrapper, SysRoleQueryResponse.class);
    }

    @Override
    public Page<SysUserQueryResponse> findUserListPage(SysRoleUserQueryRequest request) {
        if (ObjectUtil.isNotNull(request)) {
            Collection<Long> userIdList = sysUserRoleService.findUserIdListByRoleId(request.getRoleId());
            if (CollectionUtil.isNotEmpty(userIdList)) {
                SysUserQueryRequest userQueryRequest = new SysUserQueryRequest();
                userQueryRequest.setUsername(request.getUsername());
                userQueryRequest.setNickname(request.getNickname());
                userQueryRequest.setEnableStatus(request.getEnableStatus());
                userQueryRequest.setUserIds(userIdList);
                return sysUserService.findPageList(userQueryRequest);
            }
        }
        return PageUtils.getEmptyPage();
    }

    @Override
    public Collection<Long> findRoleMenuIds(Long roleId) {
        List<SysRoleMenuDomain> roleMenuList = QueryChain.of(SysRoleMenuDomain.class)
                .eq(SysRoleMenuDomain::getRoleId, roleId)
                .list();

        if (CollectionUtil.isNotEmpty(roleMenuList)) {
            Set<Long> menuIdList = roleMenuList.stream().map(SysRoleMenuDomain::getMenuId).collect(Collectors.toSet());
            return menuIdList;
        }
        return ListUtil.toList();
    }

    @Override
    public void create(SysRoleCreateRequest request) {
        ValidationHelper.validate(request);

        long count = QueryChain.of(SysRoleDomain.class)
                .eq(SysRoleDomain::getCode, request.getCode())
                .count();
        if (count > 0) {
            throw new BusinessException("角色编码已存在");
        }
        SysRoleDomain domain = MapstructHelper.convert(request, SysRoleDomain.class);
        save(domain);
    }

    @Override
    public void update(SysRoleUpdateRequest request) {
        ValidationHelper.validate(request);

        long count = QueryChain.of(SysRoleDomain.class)
                .eq(SysRoleDomain::getCode, request.getCode())
                .ne(SysRoleDomain::getId, request.getId())
                .count();
        if (count > 0) {
            throw new BusinessException("角色编码已存在");
        }
        SysRoleDomain domain = MapstructHelper.convert(request, SysRoleDomain.class);
        updateById(domain);
    }

    @Override
    public void remove(Long id) {
        long count = QueryChain.of(SysUserRoleDomain.class).eq(SysUserRoleDomain::getRoleId, id).count();
        if (count > 0) {
            throw new BusinessException("角色已被用户关联，无法删除");
        }

        Db.tx(() -> {
            removeById(id);

            sysRoleMenuService.removeByRoleId(id);
            return Boolean.TRUE;
        });
    }
}
